package kr.pe.kwonnam.replicationdatasource.jpa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserOuterService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserInnerService userInnerService;
/**
* readOnly = true에 따라 Read DB에서 데이터를 읽는다.
*
*/
@Transactional(readOnly = true)
public User findByIdRead(Integer id) {
return userRepository.findById(id);
}
/**
* readOnly = false에 따라 Write DB에서 데이터를 읽는다.
*
*/
@Transactional(readOnly = false)
public User findByIdWrite(Integer id) {
return userRepository.findById(id);
}
@Transactional(readOnly = false)
public void save(User user) throws Exception {
userRepository.save(user);
}
/**
* 비록 {@link UserInnerService#findByUserIdWithPropagationRequired(java.lang.Integer)} 가 readOnly = true라 하여도
* Propagation.REQUIRED는 기존 트랜잭션이 존재할 경우 기존 트랜잭션과 커넥션을 재사용하기 때문에 바깥 트랜잭션을 따라
* Write DB로 요청을 보낸다.
* <p/>
* 물론 기존 트랜잭션이 존재하지 않을 경우에는 새로운 트랜잭션을 맺기 때문에 올바르게 작동한다.
*/
@Transactional(readOnly = false)
public Map<String, User> findByIdWriteAndInnerReadWithPropagationRequired(Integer outerFirstId, Integer innerId, Integer outerSecondId) {
Map<String, User> users = new HashMap<String, User>();
users.put("outerFirstUser", userRepository.findById(outerFirstId));
users.put("innerUser", userInnerService.findByUserIdWithPropagationRequired(innerId));
users.put("outerSecondUser", userRepository.findById(outerSecondId));
return users;
}
/**
* {@link UserInnerService#findByUserIdWithPropagationRequiresNew(java.lang.Integer)}가 readOnly = true이고,
* Propagation.REQUIRES_NEW이면 기존 트랜잭션이 아닌 새로운 트랜잭션을 생성하며 새로운 커넥션을 맺는다.
* 따라서 innerUser를 read DB에서 읽어오게 된다.
*/
@Transactional(readOnly = false)
public Map<String, User> findByIdWriteAndInnerReadWithPropagationRequiresNew(Integer outerFirstId, Integer innerId, Integer outerSecondId) {
Map<String, User> users = new HashMap<String, User>();
users.put("outerFirstUser", userRepository.findById(outerFirstId));
users.put("innerUser", userInnerService.findByUserIdWithPropagationRequiresNew(innerId));
users.put("outerSecondUser", userRepository.findById(outerSecondId));
return users;
}
/**
* {@link UserOuterService#findByIdWriteAndInnerReadWithPoropagationMandatory(java.lang.Integer, java.lang.Integer, java.lang.Integer)}는
* 항상 바깥 트랜잭션을 따르기 때문에 바깥 트랜잭션과 커넥션을 재사용한다. 따라서 readOnly=true라도 Write DB에서 값을 읽어온다.
*/
@Transactional(readOnly = false)
public Map<String, User> findByIdWriteAndInnerReadWithPoropagationMandatory(Integer outerFirstId, Integer innerId, Integer outerSecondId) {
Map<String, User> users = new HashMap<String, User>();
users.put("outerFirstUser", userRepository.findById(outerFirstId));
users.put("innerUser", userInnerService.findByUserIdWithPropagationMandatory(innerId));
users.put("outerSecondUser", userRepository.findById(outerSecondId));
return users;
}
}